# vim:ts=4:sw=4:noet:
import os
import sys
import compileall
import shutil
import SCons

# check if we're being run from the main SConstruct
caninstall = True
try:
	Import('installbin', 'installdata')
except:
	caninstall = False

# Builder helpers
def inst(x): 
	env.Alias("install", x)
	return x

def getAllSources():
	allSources = []
	for root, dirs, files in os.walk(os.getcwd()+"/c"):
		allSources.extend([root+"/"+f for f in files if f.endswith(".py")])
	return allSources

def cleancode(target, source, env):
	cleaned = 0
	for root, dirs, files in os.walk(str(source[0])+"/c"):
		for f in [root+"/"+f for f in files if ".pyc" not in f]:
			os.remove(f)
			cleaned += 1
	print "%d sources cleaned " % cleaned

def runImagegen(target, source, config=False, extraSources = True):
	basepath = str(source[0]).split(os.sep)
	filename = str(target[0]).split(".")[0]
	cfg = config and " " or " -n"
	libpath = "/".join(basepath[:basepath.index("src")+1])
	prgpath = "/".join(basepath[:basepath.index("src")])
	if prgpath == "": prgpath = "."
	cmdline = "python %s/imagegen.py -o %s %s -q -l %s" % (
				prgpath, filename, cfg, libpath)
	if extraSources:
		cmdline += " %s" % (" ".join(map(str, source)))
	os.system(cmdline)
	
def buildExample(target, source, env):
	runImagegen(target, source)

def buildImage(target, source, env):
	runImagegen(target, source, True, False)

def compileAll(target, source, env):
	compileall.compile_dir(str(source[0]))

def buildPydocs(target, source, env):
	outdir = os.path.split(str(target[0]))[0]
	basedir = os.path.commonprefix(map(str,source))
	if basedir=="":
		basedir = "."
	cdir = basedir+"/c"
	cmdline = "epydoc --simple-term --no-private --config %s/config -o %s %s" % (
		outdir, outdir, cdir)
	os.system(cmdline)

def py2xxx(target, source, cmd, doinstall):
	cwd = os.getcwd()
	todir = str(target[0]).split(os.sep)
	todir = "/".join(todir[:todir.index("dist")])
	os.chdir(todir)
	cmdline = "python setup.py -q %s" % cmd
	os.system(cmdline)
	if caninstall:
		doinstall()
	os.chdir(cwd)

def buildPy2app(target, source, env):
	def inst():
		appdir = Dir(installbin).abspath+"/Foxtalk.app"
		if os.path.exists(appdir):
			shutil.rmtree(appdir)
		shutil.copytree("dist/Foxtalk.app", appdir)
	py2xxx(target, source, "py2app", inst)

def buildPy2exe(target, source, env):
	def inst():
		appdir = Dir(installbin).abspath
		appexe = os.path.join(appdir,"foxtalk.exe")
		if os.path.exists(appexe):
			os.remove(appexe)
		if not os.path.exists(appdir):
			os.mkdir(appdir)
		shutil.copy("dist/foxtalk.exe", appexe)
		shutil.copy("dist/python26.dll", appdir)
		shutil.copytree("dist/lib", os.path.join(appdir,"lib"))
	py2xxx(target, source, "py2exe", inst)

def buildTutorial(target, source, env):
	os.system("python %s/htmldown.py" % os.path.split(str(target[0]))[0])

def mkBuilder(func, pretty):
	return Builder(action=SCons.Action.Action(func, pretty))

def mkBuilderSuffix(func, sto, sfrom, pretty):
	return Builder(action=SCons.Action.Action(func, pretty), suffix=sto, src_suffix=sfrom)

# Builders and Environment
env = Environment(BUILDERS = {
	"Image" :      mkBuilder(buildImage,    "imagegen $TARGET"),
	"Example" :    mkBuilder(buildExample,  "imagegen $TARGET"),
	"CompileAll" : mkBuilder(compileAll,    "compileall $TARGET"),
	"Pydocs" :     mkBuilder(buildPydocs,   "pydocs $TARGET"),
	"Py2app" :     mkBuilder(buildPy2app,   "py2app $TARGET"),
	"Py2exe" :     mkBuilder(buildPy2exe,   "py2exe $TARGET"),
	"Tutorial" :   mkBuilder(buildTutorial, "tutorial $TARGET"),
})

# Examples
examples = []
for dir in os.listdir('src/examples/'):
	print os.getcwd()
	sources = Glob("src/examples/%s/*.st" % dir)
	example = env.Example("data/examples/%s.fox" % dir, sources)
	examples.append(example)
env.Alias("examples", examples)

# Main Image
img = env.Image("data/default.fox", Glob("src/*.st"))
env.Alias("image", "data/default.fox")
env.Clean(img, "data/default.cfg")

# Pydocs
docs = env.Pydocs("doc/index.html", getAllSources()+["doc/config"])
env.Alias("pydocs", docs)
env.Clean(docs, Glob("doc/*.html")+Glob("doc/epydoc.*")+Glob("doc/*.png"))

# Tutorial
tuts = []
for f in Glob("tutorial/*.txt"):
	tuts.append(env.Tutorial(str(f).replace(".txt",".html"), f))
env.Alias("tutorial", tuts)
env.Clean("tutorial", "tutorial/tutorial.html")

allTargets = ["image", "examples", "pydocs", "tutorial"]

# Executables
if sys.platform in ["darwin", "win32"]:
	setupSources = getAllSources()+["setup.py"]
	if sys.platform == "darwin":
		app = env.Py2app("dist/Foxtalk.app/Contents/Info.plist", setupSources)
	elif sys.platform == "win32":
		app = env.Py2exe("dist/foxtalk.exe", setupSources)
	env.Clean(app, ["dist", "build"])
	env.Depends(app, ["image", "examples"])
	env.Alias("app", app)
	allTargets.append("app")

# Install
if caninstall:
	if sys.platform == 'linux2':
		app=inst(env.Install(installbin, "foxtalk.py"))
		inst(env.Install(installdata, Glob("data/default.*")))
		inst(env.Install(installdata, Glob("data/*.png")))
		inst(env.Install(installdata, Glob("data/*.ico")))
		inst(env.CompileAll("compile", Glob("c")))
		inst(env.Install(installbin, "c"))
		inst(env.Command("cleancode", [installbin], cleancode))
		env.Depends(app, ["image", "examples"])
	elif sys.platform == 'darwin':
		env.Alias("install", "app")
	elif sys.platform == 'win32':
		env.Alias("install", "app")
		inst(env.Install(installdata, Glob("data/default.*")))
		inst(env.Install(installdata, Glob("data/*.png")))
		inst(env.Install(installdata, Glob("data/*.ico")))
	else:
		raise Exception("Platform %s not supported" % sys.platform)
	inst(env.Install(installdata+"/examples", Glob("data/examples/*.fox")))
	inst(env.Install(installdata+"/tutorial", Glob("tutorial/*.html")+Glob("tutorial/*.css")+Glob("tutorial/images")))
	env.Clean("install", "#release")
	allTargets.append("install")

env.Alias("all", allTargets)

Help("Targets:\n")
for t in sorted(allTargets):
	Help("  %s\n" % t)

Default(["image", "examples"])
